////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2017-2018 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file  camxfdmanagernode.h
/// @brief FDManagerNode class declarations
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef CAMXFDMANAGERNODE_H
#define CAMXFDMANAGERNODE_H

#include "camxfd4xhwutils.h"
#include "camxnode.h"
#include "camxstabilization.h"
#include "camxfdengineinterface.h"
#include "camxncsservice.h"
#include "camxncssensordata.h"

CAMX_NAMESPACE_BEGIN

CAMX_BEGIN_PACKED

/// FD HW results buffer layout definitions

static const UINT NSCSamplecount = 1;

/// @brief Structure face detect result count
struct FDHwFaceCount
{
    UINT32  dnum    : 6;    /* 5:0 */
    UINT32  unused0 : 26;   /* 31:6 */
} CAMX_PACKED;

/// @brief Structure Face center X coordinate
struct FDHwFaceCenterX
{
    UINT32  centerX : 10;   /* 9:0 */
    UINT32  unused0 : 22;   /* 31:10 */
} CAMX_PACKED;

/// @brief Structure Face center Y coordiante
struct FDHwFaceCenterY
{
    UINT32  centerY : 9;    /* 8:0 */
    UINT32  unused0 : 23;   /* 31:9 */
} CAMX_PACKED;

/// @brief Structure face size config
struct FDHwFaceSizeConf
{
    UINT32  size    : 9;    /* 8:0 */
    UINT32  conf    : 4;    /* 12:9 */
    UINT32  unused0 : 19;   /* 31:13 */
} CAMX_PACKED;

/// @brief Structure face angle pose
struct FDHwFaceAnglePose
{
    UINT32  angle   : 9;    /* 8:0 */
    UINT32  pose    : 3;    /* 11:9 */
    UINT32  unused0 : 20;   /* 31:12 */
} CAMX_PACKED;

/// @brief Structure face results from FD hardware
struct FDHwFace
{
    FDHwFaceCenterX     centerX;    ///< Face Center x-position
    FDHwFaceCenterY     centerY;    ///< Face Center y-position
    FDHwFaceSizeConf    sizeConf;   ///< Face Size, Confidence values
    FDHwFaceAnglePose   anglePose;  ///< Face Angle, Pose values
} CAMX_PACKED;

/// @brief Structure face detect results from FD hardware
struct FDHwResults
{
    FDHwFace        faces[CSLFDMaxFaces];   ///< Array of face information
    FDHwFaceCount   faceCount;              ///< Number of faces detected
    UINT32          reserved[3];            ///< Reserved fields
} CAMX_PACKED;

/// FD Metadata results structure layouts

/// @brief Structure FD Point
struct FDPoint
{
    INT32   x;  ///< Co-ordinate indicating x value
    INT32   y;  ///< Co-ordinate indicating y value
} CAMX_PACKED;

/// @brief Structure FD Meta data face rect
struct FDMetaDataFaceRect
{
    FDPoint topLeft;        ///< Point indicating top left of face rectangle
    FDPoint bottomRight;    ///< Point indicating bottom right of face rectangle
} CAMX_PACKED;

/// @brief Structure FD Metadata face landmark layout
struct FDMetaDataFaceLandmark
{
    FDPoint leftEyeCenter;  ///< Point indicating left eye center
    FDPoint rightEyeCenter; ///< Point indicating right eye center
    FDPoint mouthCenter;    ///< Point indicating mouth center
} CAMX_PACKED;

/// @brief Structure FD Metadata blink degree layout
struct FDMetaDataBlinkDegree
{
    UINT8   leftBlink;  ///< Left eye blink ratio
    UINT8   rightBlink; ///< Right eye blink ratio
} CAMX_PACKED;

/// @brief Structure FD Metadata gaze direction layout
struct FDMetaDataGazeDirection
{
    INT32   upDown;    ///< Gaze up-down direction value
    INT32   leftRight; ///< Gaze left-right direction value
    INT32   roll;      ///< Roll angle
} CAMX_PACKED;

/// @brief Structure FD Metadata gaze degree layout
struct FDMetaDataGazeDegree
{
    INT8   leftRight;  ///< Gaze left-right degree value
    INT8   topBottom;  ///< Gaze top-bottom degree value
} CAMX_PACKED;

/// @brief Structure Face Detection meta data results. These are inline with Android meta data tag expectations.
struct FDMetaDataResults
{
    UINT8                   numFaces;                           ///< Number of faces detected
    INT32                   faceID[FDMaxFaceCount];             ///< List of unique IDs for detected faces
    UINT8                   faceScore[FDMaxFaceCount];          ///< List of face confidence scores for detected faces
    FDMetaDataFaceRect      faceRect[FDMaxFaceCount];           ///< List of face rect information for detected faces
    FDMetaDataFaceLandmark  faceLandmark[FDMaxFaceCount];       ///< List of face landmark information for detected faces
    UINT8                   blinkDetected[FDMaxFaceCount];      ///< List of blink detected flags for detected faces
    FDMetaDataBlinkDegree   blinkDegree[FDMaxFaceCount];        ///< List of blink degree values for detected faces
    UINT8                   smileDegree[FDMaxFaceCount];        ///< List of smile degree information for detected faces
    UINT8                   smileConfidence[FDMaxFaceCount];    ///< List of smile confidence information for detected faces
    INT8                    gazeAngle[FDMaxFaceCount];          ///< List of gaze angle information for detected faces
    FDMetaDataGazeDirection gazeDirection[FDMaxFaceCount];      ///< List of gaze direction information for detected faces
    FDMetaDataGazeDegree    gazeDegree[FDMaxFaceCount];         ///< List of gaze degree information for detected faces
} CAMX_PACKED;

CAMX_END_PACKED

static const UINT32 DefaultFDManagerThreadDataListSize = 5;  ///< Default size of the list that holds thread data

// forward declare FD manager node
class FDManagerNode;

/// @brief Structure describing the process request information.
struct FDManagerProcessRequestData
{
    UINT64              requestId;          ///< The unique frame number for this capture request
    FDPerFrameSettings  perFrameSettings;   ///< Per frame settings
    FDHwResults         hwResults;          ///< FD HW results
};

/// @brief A unit of FDProcessingThreadData
struct FDManagerThreadData
{
    FDManagerNode*                 pInstance;             ///< this pointer of the FD manager object
    FDManagerProcessRequestData    processRequestInfo;    ///< FD Processing Request data.
};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Class that implements the FDHw node class
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FDManagerNode final : public Node
{
public:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Create
    ///
    /// @brief  Static method to create FDManagerNode Object.
    ///
    /// @param  pCreateInputData  Node create input data
    /// @param  pCreateOutputData Node create output data
    ///
    /// @return Pointer to the concrete FD Node object
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static FDManagerNode* Create(
        const NodeCreateInputData* pCreateInputData,
        NodeCreateOutputData*      pCreateOutputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// Destroy
    ///
    /// @brief  This method destroys the derived instance of the interface
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID Destroy();

protected:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeInitialize
    ///
    /// @brief  Initialize the hwl object
    ///
    /// @param  pCreateInputData  Node create input data
    /// @param  pCreateOutputData Node create output data
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeInitialize(
        const NodeCreateInputData* pCreateInputData,
        NodeCreateOutputData*      pCreateOutputData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeFinalizeInitialization
    ///
    /// @brief  Method to finalize the initialization of the node in the pipeline
    ///
    /// @param  pFinalizeInitializationData Finalize data
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeFinalizeInitialization(
        FinalizeInitializationData* pFinalizeInitializationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PostPipelineCreate
    ///
    /// @brief  virtual method to be called at NotifyTopologyCreated time; node should take care of updates and initialize
    ///         blocks that has dependency on other nodes in the topology at this time.
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult PostPipelineCreate();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ExecuteProcessRequest
    ///
    /// @brief  Pure virtual method to trigger process request for the hwl node object.
    ///
    /// @param  pExecuteProcessRequestData Process request data
    ///
    /// @return CamxResultSuccess if successful and 0 dependencies, dependency information otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ExecuteProcessRequest(
        ExecuteProcessRequestData* pExecuteProcessRequestData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessingNodeFinalizeInputRequirement
    ///
    /// @brief  Virtual method implemented by FDHw node to determine its input buffer requirements based on all the output
    ///         buffer requirements
    ///
    /// @param  pBufferNegotiationData  Negotiation data for all output ports of a node
    ///
    /// @return Success if the negotiation was successful, Failure otherwise
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult ProcessingNodeFinalizeInputRequirement(
        BufferNegotiationData* pBufferNegotiationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FinalizeBufferProperties
    ///
    /// @brief  Finalize the buffer properties of each output port
    ///
    /// @param  pBufferNegotiationData Buffer negotiation data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual VOID FinalizeBufferProperties(
        BufferNegotiationData* pBufferNegotiationData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OnStreamOn
    ///
    /// @brief  Streamon command
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult OnStreamOn();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OnStreamOff
    ///
    /// @brief  Streamoff command
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual CamxResult OnStreamOff();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ~FDManagerNode
    ///
    /// @brief  Destructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    virtual ~FDManagerNode();

private:
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FDManagerNode
    ///
    /// @brief  Constructor
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    FDManagerNode();
    FDManagerNode(const FDManagerNode&) = delete;                 ///< Disallow the copy constructor.
    FDManagerNode& operator=(const FDManagerNode&) = delete;      ///< Disallow assignment operator.

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FillInputBufferRequirments
    ///
    /// @brief  Fill input buffer requirments
    ///
    /// @param  pInputBufferRequirement Pointer to input buffer requirment
    /// @param  portId                  Input port id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult FillInputBufferRequirments(
        BufferRequirement* pInputBufferRequirement,
        UINT32             portId);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetPerFrameMetaDataSettings
    ///
    /// @brief  Checks dependencies to get meta data information for this request id
    ///
    /// @param  pNodeRequestData Pointer to process request data
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetPerFrameMetaDataSettings(
        const NodeProcessRequestData* const pNodeRequestData,
        FDPerFrameSettings*                 pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFrameCropInfo
    ///
    /// @brief  Get crop information for this request
    ///
    /// @param  pNodeRequestData Pointer to process request data
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetFrameCropInfo(
        const NodeProcessRequestData* const pNodeRequestData,
        FDPerFrameSettings*                 pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetDeviceOrientation
    ///
    /// @brief  Get device orientation information
    ///
    /// @param  pNodeRequestData Pointer to process request data
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetDeviceOrientation(
        const NodeProcessRequestData* const pNodeRequestData,
        FDPerFrameSettings*                 pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// DetermineFrameSettings
    ///
    /// @brief  Determine frame settings for this request id
    ///
    /// @param  pNodeRequestData  Pointer to process request data
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID DetermineFrameSettings(
        const NodeProcessRequestData* const pNodeRequestData,
        FDPerFrameSettings*                 pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetAndProcessFDResults
    ///
    /// @brief  Get results and process
    ///
    /// @param  requestId            Request id
    /// @param  pEnabledPorts        Pointer to active ports
    /// @param  pPerFrameSettings    Frame settings for this request id
    /// @param  pRequestHandlingDone Request handling done flag
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetAndProcessFDResults(
        UINT64                 requestId,
        PerRequestActivePorts* pEnabledPorts,
        FDPerFrameSettings*    pPerFrameSettings,
        BOOL*                  pRequestHandlingDone);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConvertResultsFromProcessingToReference
    ///
    /// @brief  Convert FDResults ROI from w.r.t Processing frame to w.r.t Reference Frame
    ///
    /// @param  pProcessingResults FD Results w.r.t processing frame
    /// @param  pReferenceResults  FD Results w.r.t reference frame
    /// @param  pPerFrameSettings  Frame settings for this request id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ConvertResultsFromProcessingToReference(
        FDResults*          pProcessingResults,
        FDResults*          pReferenceResults,
        FDPerFrameSettings* pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ConvertFromProcessingResultsToReferenceFaceROIInfo
    ///
    /// @brief  Convert FDResults ROI from w.r.t Processing frame to FD Property Results w.r.t Reference Frame
    ///
    /// @param  pUnstabilizedResults Unstabilized FD Results w.r.t processing frame
    /// @param  pStabilizedResults   Stabilized FD Results w.r.t processing frame
    /// @param  pFaceROIInfo         FD Property Results w.r.t reference frame
    /// @param  pPerFrameSettings    Frame settings for this request id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ConvertFromProcessingResultsToReferenceFaceROIInfo(
        FDResults*                  pUnstabilizedResults,
        FDResults*                  pStabilizedResults,
        FaceROIInformation*         pFaceROIInfo,
        const FDPerFrameSettings*   pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckROIBound
    ///
    /// @brief  Check and adjust top, left, width, and height values so that ROI falls within frame.
    ///
    /// @param  pResults FD Results w.r.t processing frame
    /// @param  width    Width of the frame
    /// @param  height   Height of the frame
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID CheckROIBound(
        FDResults*  pResults,
        INT32       width,
        INT32       height);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ExecuteFDResultsProcessing
    ///
    /// @brief  Execute FD manager results processing
    ///
    /// @param  pHWResults        Pointer to HW results
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ExecuteFDResultsProcessing(
        const FDHwResults*          pHWResults,
        const FDPerFrameSettings*   pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishFDFrameSettings
    ///
    /// @brief  Publish frame settings
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PublishFDFrameSettings(
        FDPerFrameSettings* pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFDFrameSettings
    ///
    /// @brief  Get FD per frame settings
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult GetFDFrameSettings(
        FDPerFrameSettings* pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFdFilterEngine
    ///
    /// @brief  GEt FD engine type
    ///
    /// @return FDEngineType
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    FDEngineType GetFdFilterEngine();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishFDResults
    ///
    /// @brief  Publish FD results
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PublishFDResults(
        FDPerFrameSettings* pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishFDResultsToMetadata
    ///
    /// @brief  Publish FD results to app
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    /// @param  pFaceROIInfo      Pointer to FD results to publish
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PublishFDResultsToMetadata(
        FDPerFrameSettings* pPerFrameSettings,
        FaceROIInformation* pFaceROIInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishFDResultsToVendorTag
    ///
    /// @brief  Publish FD results to OEM vendor tag
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    /// @param  pFaceROIInfo      Pointer to FD Face ROI info to publish
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PublishFDResultsToVendorTag(
        FDPerFrameSettings* pPerFrameSettings,
        FaceROIInformation* pFaceROIInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PublishFDResultstoUsecasePool
    ///
    /// @brief  Publish preview dimensions
    ///
    /// @param  pFaceROIInfo  Pointer to FD results to publish to usecasepool
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PublishFDResultstoUsecasePool(
        FaceROIInformation* pFaceROIInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetFDResultsFromUsecasePool
    ///
    /// @brief  Publish preview dimensions
    ///
    /// @param  pFaceROIInfo  Pointer to FD results to publish to usecasepool
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetFDResultsFromUsecasePool(
        FaceROIInformation*  pFaceROIInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetDependencies
    ///
    /// @brief  Sets up dependencies for properties and buffer
    ///
    /// @param  pNodeRequestData    Pointer to process request data
    /// @param  pEnabledPorts       Pointer to active ports
    /// @param  pPerFrameSettings   Pointer to settings for request
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID SetDependencies(
        NodeProcessRequestData* pNodeRequestData,
        PerRequestActivePorts*  pEnabledPorts,
        FDPerFrameSettings*     pPerFrameSettings);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FDManagerThreadCb
    ///
    /// @brief  Thread callback function.
    ///
    /// @param  pArg Pointer to callback data
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    static VOID* FDManagerThreadCb(
        VOID* pArg);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// FDManagerJobHandler
    ///
    /// @brief  Handles Jobs received from FDManagerThreadCb function
    ///
    /// @param  pThreadData Pointer to thread data
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult FDManagerJobHandler(
        FDManagerThreadData* pThreadData);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// OnProcessRequest
    ///
    /// @brief  Function to Process a new request.
    ///
    /// @param  pProcessRequestData Pointer to process request structure to be filled
    /// @param  pProcessHandled     Out pointer to indicate if process handled
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult OnProcessRequest(
        const FDManagerProcessRequestData* pProcessRequestData,
        BOOL*                              pProcessHandled);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetLocalThreadDataMemory
    ///
    /// @brief  Get an instance from the Thread Data memory pool
    ///
    /// @return Returns a pointer from Thread Data memory pool
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    FDManagerThreadData* GetLocalThreadDataMemory();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// StabilizeFaces
    ///
    /// @brief  Uses the latest data from Face Detection to update the historical stabilization data and updates the latest
    ///         data to stabilized values
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    /// @param  pUnstabilized     Pointer to result data of current data
    /// @param  pStabilized       Pointer to result data that will be filled with stabilized results
    ///
    /// @return CamxResultSuccess if success
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult StabilizeFaces(
        const FDPerFrameSettings* pPerFrameSettings,
        FDResults*                pUnstabilized,
        FDResults*                pStabilized);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// ProcessFDEngineResults
    ///
    /// @brief  Process results through FD engine
    ///
    /// @param  pPerFrameSettings Frame settings for this request id
    /// @param  pHWResults        Current HW results for this frame
    /// @param  pEngineResults    Final results from FD engine for this frame
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult ProcessFDEngineResults(
        const FDPerFrameSettings*     pPerFrameSettings,
        FDIntermediateResults*        pHWResults,
        FDResults*                    pEngineResults);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// InitializeStabilization
    ///
    /// @brief  Initialize stabilization
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult InitializeStabilization();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupFDEngineConfig
    ///
    /// @brief  Process results through FD engine
    ///
    /// @param  pFDConfig     Pointer to FD confiugration
    /// @param  pEngineConfig Pointer to FD engine config to update with tuning values
    ///
    /// @return CamxResultSuccess if successful
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupFDEngineConfig(
        const FDConfig* pFDConfig,
        FDEngineConfig* pEngineConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintFDResults
    ///
    /// @brief  Print face detection results
    ///
    /// @param  pLogTag     Log tag that identifies the results
    /// @param  frameId     FrameID corresponding to the results
    /// @param  width       Width of the frame
    /// @param  height      Height of the frame
    /// @param  numFaces    Number of faces
    /// @param  pFaceInfo   Face info array
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrintFDResults(
        const CHAR* pLogTag,
        UINT64      frameId,
        UINT32      width,
        UINT32      height,
        UINT8       numFaces,
        FDFaceInfo* pFaceInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PrintFDFaceROIInfo
    ///
    /// @brief  Print face ROI information
    ///
    /// @param  pLogTag         Log tag that identifies the results
    /// @param  frameId         FrameID corresponding to the results
    /// @param  width           Width of the frame
    /// @param  height          Height of the frame
    /// @param  pFaceROIInfo    Face info array
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID PrintFDFaceROIInfo(
        const CHAR*         pLogTag,
        UINT64              frameId,
        UINT32              width,
        UINT32              height,
        FaceROIInformation* pFaceROIInfo);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// CheckFDConfigChange
    ///
    /// @brief  Check and load if there is a change in FD configuration
    ///
    /// @param  pFDConfig   Pointer to load FD confiugration
    ///
    /// @return TRUE if config has been updated.
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL CheckFDConfigChange(
        FDConfig* pFDConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// GetStabilizationConfig
    ///
    /// @brief  Check and load if there is a change in FD configuration
    ///
    /// @param  pFDConfig               Pointer to FD confiugration
    /// @param  pStabilizationConfig    Pointer to load stabilization confiugration
    ///
    /// @return None
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    VOID GetStabilizationConfig(
        const FDConfig*      pFDConfig,
        StabilizationConfig* pStabilizationConfig);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupNCSLink
    ///
    /// @brief  Set up a link to the NCS service from this node
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupNCSLink();

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// SetupNCSLinkForSensor
    ///
    /// @brief  Set up a link to the NCS service for sensor
    ///
    /// @param  sensorType    Sensor type for which NCS service is registered
    ///
    /// @return Success or failure
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult SetupNCSLinkForSensor(
        NCSSensorType  sensorType);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// PopulateGravityData
    ///
    /// @brief  Retrieves gyro info from NCS interface
    ///
    /// @param  gravityValues    gravity values need to be updated
    ///
    /// @return CamxResultSuccess if successful
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    CamxResult PopulateGravityData(
        float gravityValues[]);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /// IsFDManagerNodeStreamOff
    ///
    /// @brief  Checks if FD manager node is streamed off
    ///
    /// @return TRUE if streamed off else FALSE
    ///
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    BOOL IsFDManagerNodeStreamOff();

    UINT32                  m_FDFrameWidth;                         ///< FD Processing frame width
    UINT32                  m_FDFrameHeight;                        ///< FD Processing frame height
    UINT32                  m_FDFrameStride;                        ///< FD Processing frame stride
    UINT32                  m_FDFrameScanline;                      ///< FD Processing frame scanline
    CHIDimension            m_sensorDimension;                      ///< Sensor frame dimension
    CHIRectangle            m_CAMIFMap;                             ///< CAMIF mapping in Active Array
    CHIDimension            m_activeArrayDimension;                 ///< Active array dimension
    ThreadManager*          m_pThreadManager;                       ///< Pointer to thread manager.
    JobHandle               m_hThread;                              ///< Thread handle
    FD4xHwUtils             m_FDHwUtils;                            ///< HW Util class
    Stabilization*          m_pStabilizer;                          ///< Stabilizer to stabilize FD result data
    FDEngineHandle          m_hFDEngineHandle;                      ///< FD Engine handle
    CamxDimension           m_baseFDHWDimension;                    ///< Base FD HW dimension
    FDConfig                m_FDConfig;                             ///< Face detection tuning configuration
    BYTE*                   m_pUVImageAddress[MaxRequestQueueDepth];///< Copy of input frame for UV
    BYTE*                   m_pImageAddress[MaxRequestQueueDepth];  ///< Copy of input frame
    UINT32                  m_processedFrameCnt;                    ///< Total number of frames processed
    UINT32                  m_skippedFrameCnt;                      ///< Total number of frames skipped
    BOOL                    m_startTimeSaved;                       ///< Whether start time is saved for determining fps skip
    CamxTime                m_startTime;                            ///< First frame start time
    CamxTime                m_currentTime;                          ///< Current frame time
    UINT32                  m_numFacesDetected;                     ///< Number of faces detected in last processed frame
    BOOL                    m_isFrontCamera;                        ///< Whether this instance is for front camera
    BOOL                    m_isVideoMode;                          ///< Whether current mode is video
    NCSSensor*              m_pNCSSensorHandleGravity;              ///< NCS Sensor Gravity handle.
    NCSService*             m_pNCSServiceObject;                    ///< NCS Service object pointer.
    Mutex*                  m_pLock;                                ///< Mutex to protect FD manager internal thread state

    const CameraConfigurationInformation* m_pCameraConfigInfo;      ///< Pointer to Camera configuration information
    LightweightDoublyLinkedList           m_threadDataList;         ///< List to track the thread data
    BOOL                                  m_isNodeStreamedOff;      ///< Flag to indicate if node streamed off

    PerRequestActivePorts*  m_pPerRequestPorts;                     ///< Ports info
};

CAMX_NAMESPACE_END

#endif // CAMXFDMANAGERNODE_H
